package com.byd.fastevent;

import java.util.NoSuchElementException;

public class FixedList<T> {
	private int mSize;
	private final int mMaxSize;
	private final Item<T> mItem;
	private final Item<T>[] mItems;

	private static class Item<T> {
		T data;
		Item<T> prev;
		Item<T> next;
		boolean use;

		Item() {
			data = null;
			this.prev = this;
			this.next = this;
		}
	}

	/** @param maxSize 不重要的数据的缓冲大小，不重要数据数量大于缓冲大小时，会将之前的数据丢弃掉 */
	@SuppressWarnings("unchecked")
	public FixedList(int maxSize) {
		mMaxSize = Math.max(maxSize, 0) + 1;
		mItem = new Item<T>();
		mItems = new Item[mMaxSize];
	}

	private Item<T> obtainItem(boolean importance) {
		if(importance) {
			return new Item<T>();
		}
		for (int i = 0; i < mMaxSize; i++) {
			if(mItems[i] == null) {
				return mItems[i] = new Item<T>();
			}
			else if(!mItems[i].use) {
				return mItems[i];
			}
		}
		return null;
	}

	private Item<T> obtainItem(T t, Item<T> prev, Item<T> next, boolean importance) {
		Item<T> item = obtainItem(importance);
		if(item == null) {
			item = removeFirstInner();
		}
		item.use = true;
		item.data = t;
		item.prev = prev;
		item.next = next;
		return item;
	}

	public synchronized void add(T t) {
		final boolean importance = t != null && t instanceof IFastEvent && ((IFastEvent) t).isImportance();
		final Item<T> oldLast = mItem.prev;
		final Item<T> newLast = obtainItem(t, oldLast, mItem, importance);
		if(oldLast.equals(newLast)) {
			newLast.prev = mItem;
			newLast.next = mItem;
			mItem.next = newLast;
		}
		else {
			oldLast.next = newLast;
		}
		mItem.prev = newLast;
		mSize++;
	}

	public Item<T> removeFirstInner() {
		final Item<T> oldFirst = mItem.next;
		if(!oldFirst.equals(mItem)) {
			final Item<T> newFirst = oldFirst.next;
			mItem.next = newFirst;
			newFirst.prev = mItem;
			oldFirst.use = false;
			mSize--;
			return oldFirst;
		}
		throw new NoSuchElementException("size: " + mSize);
	}

	public synchronized T removeFirst() {
		return removeFirstInner().data;
	}

	public boolean isEmpty() {
		return mSize == 0;
	}

	@Override
	public String toString() {
		Item<T> item = mItem.next;
		final StringBuilder builder = new StringBuilder();
		int i = 0;
		while (!item.equals(mItem)) {
			builder.append("[");
			builder.append(i++);
			builder.append("]: ");
			builder.append(item.data);
			builder.append("\r\n");
			item = item.next;
		}
		if(builder.length() == 0) {
			builder.append("list is empty");
		}
		return builder.toString();
	}
}
